#include "plbtTypes.h"
#include "../core/LuaUtils.h"
#include "btBulletDynamicsCommon.h"

RegisterCustomDatatype<luabind_btvec> g_btvec_dt("btVector3");
RegisterCustomDatatype<luabind_btquat> g_btquat_dt("btQuaternion");
RegisterCustomDatatype<luabind_bttrans> g_bttrans_dt("btTransform");

void luabind_btvec::registerFunctions(lua_State* L)
{
	luabind_btvec::pushStaticFuncs(L);
}

void luabind_btquat::registerFunctions(lua_State* L)
{
	luabind_btquat::pushStaticFuncs(L);
}

void luabind_bttrans::registerFunctions(lua_State* L)
{
	luabind_bttrans::pushStaticFuncs(L);
}

int li_delete_btvec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	delete op;
	return 0;
}

int li_delete_btquat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	delete op;
	return 0;
}

int li_delete_bttrans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	delete op;
	return 0;
}

void luabind_btvec::pushStaticFuncs(lua_State* L)
{
	static const struct luaL_Reg mylib [] = {
		{"PlusEquals", li_plusEquals_vec},
		{"MinusEquals", li_minusEquals_vec},
		{"Plus", li_plus_vec},
		{"Minus", li_minus_vec},
		{"TimesEquals", li_timesEquals_vec},
		{"Times", li_times_vec},
		{"Dotprod", li_dotprod_vec},
		{"Norm_inplace", li_norm_inplace_vec},
		{"Normalized", li_normalized_vec},
		{"Distance2", li_distance2_vec},
		{"Distance", li_distance_vec},
		{"Cross", li_cross_vec},
		{"Rotate_axisangle", li_rotate_axisangle_vec},
		{"Anglebetween", li_anglebetween_vec},
		{"Get", li_get_vec},
		{"Set", li_set_vec},
		{"ToTable", li_totable_vec},
		{"__gc", li_delete_btvec},
		{NULL, NULL}  /* sentinel */
	};

	// dump them into said table
	luaL_register(L, NULL, mylib);
}

void luabind_btquat::pushStaticFuncs(lua_State* L)
{
	static const struct luaL_Reg mylib [] = {
		{"SetRotation_axisangle", li_setRotation_axisangle_quat},
		{"SetRotation_euler", li_setRotation_euler_quat},
		{"SetRotationZYX_euler", li_setRotationZYX_euler_quat},
		{"TimesEquals", li_timesEquals_quat},
		{"Times", li_times_quat},
		{"Norm_inplace", li_norm_inplace_quat},
		{"Normalized", li_normalized_quat},
		{"GetAngle", li_getAngle_quat},
		{"GetAxis", li_getAxis_quat},
		{"Get", li_get_quat},
		{"Set", li_set_quat},
		{"Inverse", li_inverse_quat},
		{"Slerp", li_slerp_quat},
		{"Rotatevec", li_rotatevec_quat},
		{"FromVecBasis", li_fromVecBasis_quat},
		{"FromVecBasisCol", li_fromVecBasisCol_quat},
		{"ToVecBasis", li_toVecBasis_quat},
		{"ToTableXYZW", li_totablexyzw_quat},
		{"ToTableWXYZ", li_totablewxyz_quat},
		{"__gc", li_delete_btquat},
		{NULL, NULL}  /* sentinel */
	};

	// dump them into said table
	luaL_register(L, NULL, mylib);
}

void luabind_bttrans::pushStaticFuncs(lua_State* L)
{
	static const struct luaL_Reg mylib [] = {
		{"SetRotation", li_setRotation_trans},
		{"SetOrigin", li_setOrigin_trans},
		{"GetRotation", li_getRotation_trans},
		{"GetOrigin", li_getOrigin_trans},
		{"TimesEquals", li_timesEquals_trans},
		{"Times", li_times_trans},
		{"Inverse", li_inverse_trans},
		{"InverseTimes", li_inverseTimes_trans},
		{"ApplyTo", li_applyTo_trans},
		{"FromMatrix", li_fromMatrix_trans},
		{"ToMatrix", li_toMatrix_trans},
		{"__gc", li_delete_bttrans},
		{NULL, NULL}  /* sentinel */
	};

	// dump them into said table
	luaL_register(L, NULL, mylib);
}

int luabind_btvec::li_plusEquals_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	//op->plusEquals_vec(a1);
	(*op) += (*a1);
	
	return 0;
}


int luabind_btvec::li_minusEquals_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	//op->minusEquals_vec(a1);
	(*op) -= (*a1);
	
	return 0;
}


int luabind_btvec::li_plus_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	btVector3 ret = (*op) + (*a1); //op->plus_vec(a1);
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_btvec::li_minus_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	btVector3 ret = (*op) - (*a1); //op->minus_vec(a1);
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_btvec::li_timesEquals_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	float a1 = (float)lua_tonumber(L, 2);
	//op->timesEquals_vec(a1);
	(*op) *= a1;
	
	return 0;
}


int luabind_btvec::li_times_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	float a1 = (float)lua_tonumber(L, 2);
	btVector3 ret = (*op) * a1; //op->times_vec(a1);
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_btvec::li_dotprod_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	float ret = op->dot(*a1); //op->dotprod_vec(a1);
	lua_pushnumber(L, ret);
	return 1;
}


int luabind_btvec::li_norm_inplace_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	op->normalize();
	//op->norm_inplace_vec();
	
	return 0;
}


int luabind_btvec::li_normalized_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3 ret = op->normalized();
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_btvec::li_distance2_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	float ret = op->distance2(*a1);
	lua_pushnumber(L, ret);
	return 1;
}


int luabind_btvec::li_distance_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	float ret = op->distance(*a1);
	lua_pushnumber(L, ret);
	return 1;
}


int luabind_btvec::li_cross_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	btVector3 ret = op->cross(*a1);
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_btvec::li_rotate_axisangle_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	float a2 = (float)lua_tonumber(L, 3);
	btVector3 ret = op->rotate(*a1, a2); // ??
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_btvec::li_anglebetween_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	float ret = op->angle(*a1);
	lua_pushnumber(L, ret);
	return 1;
}


int luabind_btvec::li_get_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int a1 = (int)lua_tointeger(L, 2);
	float ret = (*op)[a1];
	lua_pushnumber(L, ret);
	return 1;
}


int luabind_btvec::li_set_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int a1 = (int)lua_tointeger(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	(*op)[a1] = a2;
	//op->set_vec(a1, a2);
	
	return 0;
}

int luabind_btvec::li_totable_vec(lua_State* L)
{
	btVector3* op = pop_custom<btVector3>(L, 1, "btVector3");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	lua_newtable(L);
	for(int i = 0; i < 3; ++i)
	{
		lua_pushnumber(L, (*op)[i]);
		lua_rawseti(L, -2, i+1);
	}
	return 1;
}

int luabind_btquat::li_setRotation_axisangle_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	float a2 = (float)lua_tonumber(L, 3);
	//op->setRotation_axisangle_quat(a1, a2);
	op->setRotation(*a1, a2);
	
	return 0;
}


int luabind_btquat::li_setRotation_euler_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	float a1 = (float)lua_tonumber(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	op->setEuler(a1, a2, a3);
	
	return 0;
}


int luabind_btquat::li_setRotationZYX_euler_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	float a1 = (float)lua_tonumber(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	float a3 = (float)lua_tonumber(L, 4);
	op->setEulerZYX(a1, a2, a3);
	
	return 0;
}


int luabind_btquat::li_timesEquals_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btQuaternion* a1 = pop_custom<btQuaternion>(L, 2, "btQuaternion"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	//op->timesEquals_quat(a1);
	(*op) *= (*a1);
	
	return 0;
}


int luabind_btquat::li_times_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btQuaternion* a1 = pop_custom<btQuaternion>(L, 2, "btQuaternion"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	btQuaternion ret = (*op) * (*a1);//op->times_quat(a1);
	push_custom<btQuaternion>(L, &ret, "btQuaternion");
	return 1;
}


int luabind_btquat::li_norm_inplace_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	op->normalize();
	//op->norm_inplace_quat();
	
	return 0;
}


int luabind_btquat::li_normalized_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btQuaternion ret = op->normalized();
	push_custom<btQuaternion>(L, &ret, "btQuaternion");
	return 1;
}


int luabind_btquat::li_getAngle_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	float ret = op->getAngle();
	lua_pushnumber(L, ret);
	return 1;
}


int luabind_btquat::li_getAxis_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3 ret = op->getAxis();
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_btquat::li_get_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int a1 = (int)lua_tointeger(L, 2);
	float ret = (*op)[a1];//op->get_quat(a1);
	lua_pushnumber(L, ret);
	return 1;
}


int luabind_btquat::li_set_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	int a1 = (int)lua_tointeger(L, 2);
	float a2 = (float)lua_tonumber(L, 3);
	(*op)[a1] = a2;
	//op->set_quat(a1, a2);
	
	return 0;
}


int luabind_btquat::li_inverse_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btQuaternion ret = op->inverse();
	push_custom<btQuaternion>(L, &ret, "btQuaternion");
	return 1;
}


int luabind_btquat::li_slerp_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btQuaternion* a1 = pop_custom<btQuaternion>(L, 2, "btQuaternion"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	float a2 = (float)lua_tonumber(L, 3);
	btQuaternion ret = op->slerp(*a1, a2);
	push_custom<btQuaternion>(L, &ret, "btQuaternion");
	return 1;
}


int luabind_btquat::li_rotatevec_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	btVector3 ret = quatRotate(*op, *a1);
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}

int luabind_btquat::li_fromVecBasis_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3");
	btVector3* a2 = pop_custom<btVector3>(L, 3, "btVector3");
	btVector3* a3 = pop_custom<btVector3>(L, 4, "btVector3");
	if(a1 == NULL || a2 == NULL || a3 == NULL)
	{
		LOG(logERROR) << "Null input in luabind_btquat::li_fromvecbasis_quat";
		return 0;
	}
	btMatrix3x3 tempMat;
	tempMat[0] = (*a1);
	tempMat[1] = (*a2);
	tempMat[2] = (*a3);
	btQuaternion ret;
	tempMat.getRotation(ret);

	push_custom<btQuaternion>(L, &ret, "btQuaternion");
	return 1;
}

int luabind_btquat::li_fromVecBasisCol_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3");
	btVector3* a2 = pop_custom<btVector3>(L, 3, "btVector3");
	btVector3* a3 = pop_custom<btVector3>(L, 4, "btVector3");
	if(a1 == NULL || a2 == NULL || a3 == NULL)
	{
		LOG(logERROR) << "Null input in luabind_btquat::li_fromvecbasis_quat";
		return 0;
	}
	btVector3* vecs[3] = {a1, a2, a3};
	btMatrix3x3 tempMat;
	for(int i = 0; i < 3; ++i)
	{
		for(int j = 0; j < 3; ++j)
		{
			//LOG(logDEBUG) << (*vecs[j])[i];
			tempMat[i][j] = (*vecs[j])[i];
		}
	}

	//for(int i = 0; i < 3; ++i)
	//{
	//	for(int j = 0; j < 3; ++j)
	//	{
	//		LOG(logDEBUG) << tempMat[i][j];
	//	}
	//}

	btQuaternion ret;
	tempMat.getRotation(ret);

	push_custom<btQuaternion>(L, &ret, "btQuaternion");
	return 1;
}

int luabind_btquat::li_totablexyzw_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	lua_newtable(L);
	for(int i = 0; i < 4; ++i)
	{
		lua_pushnumber(L, (*op)[i]);
		lua_rawseti(L, -2, i+1);
	}
	return 1;
}

int luabind_btquat::li_totablewxyz_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	lua_newtable(L);
	for(int i = 0; i < 3; ++i)
	{
		lua_pushnumber(L, (*op)[i]);
		lua_rawseti(L, -2, i+2);
	}
	lua_pushnumber(L, (*op)[3]);
	lua_rawseti(L, -2, 1);
	return 1;
}

int luabind_btquat::li_toVecBasis_quat(lua_State* L)
{
	btQuaternion* op = pop_custom<btQuaternion>(L, 1, "btQuaternion");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btMatrix3x3 tempMat(*op);
	btVector3& v1 = tempMat[0]; //.getBasis(0);
	btVector3& v2 = tempMat[1]; //.getBasis(1);
	btVector3& v3 = tempMat[2]; //.getBasis(2);
	push_custom<btVector3>(L, &v1, "btVector3");
	push_custom<btVector3>(L, &v2, "btVector3");
	push_custom<btVector3>(L, &v3, "btVector3");
	return 3;
}

int luabind_bttrans::li_setRotation_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btQuaternion* a1 = pop_custom<btQuaternion>(L, 2, "btQuaternion"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	op->setRotation(*a1);
	
	return 0;
}


int luabind_bttrans::li_setOrigin_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	op->setOrigin(*a1);
	
	return 0;
}


int luabind_bttrans::li_getRotation_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btQuaternion ret = op->getRotation();
	push_custom<btQuaternion>(L, &ret, "btQuaternion");
	return 1;
}


int luabind_bttrans::li_getOrigin_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3 ret = op->getOrigin();
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


int luabind_bttrans::li_timesEquals_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btTransform* a1 = pop_custom<btTransform>(L, 2, "btTransform"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	//op->timesEquals_trans(a1);
	(*op) *= (*a1);
	
	return 0;
}


int luabind_bttrans::li_times_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btTransform* a1 = pop_custom<btTransform>(L, 2, "btTransform"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	//op->times_trans(a1);
	btTransform ret = (*op) * (*a1);
	push_custom<btTransform>(L, &ret, "btTransform");
	return 1;
}


int luabind_bttrans::li_inverse_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btTransform ret = op->inverse();
	push_custom<btTransform>(L, &ret, "btTransform");
	return 1;
}


int luabind_bttrans::li_inverseTimes_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btTransform* a1 = pop_custom<btTransform>(L, 2, "btTransform"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	btTransform ret = op->inverseTimes(*a1);
	push_custom<btTransform>(L, &ret, "btTransform");
	return 1;
}


int luabind_bttrans::li_applyTo_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	btVector3* a1 = pop_custom<btVector3>(L, 2, "btVector3"); if(a1 == NULL){ LOG(logERROR) << "Null input."; return 0; }
	//op->applyTo_trans(a1);
	btVector3 ret = (*op) * (*a1);
	push_custom<btVector3>(L, &ret, "btVector3");
	return 1;
}


// TODO: implement these
int luabind_bttrans::li_fromMatrix_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	float a1 = (float)lua_tonumber(L, 2);
	//op->fromMatrix_trans(a1);
	
	return 0;
}


int luabind_bttrans::li_toMatrix_trans(lua_State* L)
{
	btTransform* op = pop_custom<btTransform>(L, 1, "btTransform");
	if(op == NULL){
		LOG(logERROR) << "Null self!";
	return 0;}
	float ret = 0.0f; //op->toMatrix_trans();
	lua_pushnumber(L, ret);
	return 1;
}